package com.example.core.context;

import com.example.common.config.Rule;
import com.example.common.util.AssertUtil;
import com.example.core.request.GatewayRequest;
import com.example.core.response.GatewayResponse;
import io.micrometer.core.instrument.Timer;
import io.netty.channel.ChannelHandlerContext;
import io.netty.util.ReferenceCountUtil;
import lombok.Getter;
import lombok.Setter;


/**
 * @Author Peng Yisheng
 * @Date 2024/11/4 17:24
 * @Description 网关核心上下文类, 包含请求、响应和一系列规则
 */
public class GatewayContext extends BaseContext {
    @Setter
    @Getter
    private GatewayRequest request;

    @Setter
    @Getter
    private GatewayResponse response;

    @Setter
    @Getter
    private Rule rule;

    @Setter
    @Getter
    private boolean gray;

    @Setter
    @Getter
    private int currentRetryTimes = 0;

    @Setter
    @Getter
    private Timer.Sample timerSample;

    public GatewayContext(String protocol, ChannelHandlerContext nettyCtx, boolean keepAlive,
                          GatewayRequest request, Rule rule) {
        super(protocol, nettyCtx, keepAlive);
        this.request = request;
        this.rule = rule;
        this.gray = request.isGray();
    }

    public static class Builder {
        private String protocol;
        private ChannelHandlerContext nettyCtx;
        private boolean keepAlive;
        private GatewayRequest request;
        private Rule rule;

        private Builder() {

        }

        public Builder setProtocol(String protocol) {
            this.protocol = protocol;
            return this;
        }

        public Builder setNettyCtx(ChannelHandlerContext nettyCtx) {
            this.nettyCtx = nettyCtx;
            return this;
        }

        public Builder setKeepAlive(boolean keepAlive) {
            this.keepAlive = keepAlive;
            return this;
        }

        public Builder setRequest(GatewayRequest request) {
            this.request = request;
            return this;
        }

        public Builder setRule(Rule rule) {
            this.rule = rule;
            return this;
        }

        public GatewayContext build() {
            AssertUtil.notNull(protocol, "protocol 不能为空");
            AssertUtil.notNull(nettyCtx, "nettyCtx 不能为空");
            AssertUtil.notNull(request, "request 不能为空");
            AssertUtil.notNull(rule, "rule 不能为空");
            return new GatewayContext(protocol, nettyCtx, keepAlive, request, rule);
        }
    }

    public String getUniqueId() {
        return request.getUniqueId();
    }

    /**
     * 重写父类释放资源方法，用于正在释放资源
     */
    public void releaseRequest() {
        if (requestReleased.compareAndSet(false, true)) {
            ReferenceCountUtil.release(request.getFullHttpRequest());
        }
    }

}
